#ifndef __PVMVOICEMOD_H__
#define __PVMVOICEMOD_H__

#include "lib/pvmvoice.h"
#include "pvm/pvmapi.h"
#include "lib/decoders/mod/pvmmodstruct.h"

#include "lib/memory/pvmmemory.h"
class PVMVoiceSourceMOD;

class PVMVoiceMOD : public IPVMVoice, public PVMAllocableObject
{
protected:
	PVMVoiceMOD();
public:
	virtual ~PVMVoiceMOD();

	virtual void GetFormat(pvm_uint32 &samplesPerSecond, pvm_uint32 &bitsperSample, pvm_uint32 &chanels);
	virtual pvm_uint32 GetSamplesPerSecond();
	virtual pvm_uint32 GetBitsPerSample();
	virtual pvm_uint32 GetChanelsNum();

	virtual pvm_uint32 FillBuffer(void *buffer, pvm_uint32 numSamples);
	virtual void SetPause(pvm_bool pause);
	virtual pvm_bool GetPause();
	virtual pvm_bool IsAlive();
	virtual void DoDestroy();

	virtual void OnIdle();

	virtual void SetLoopCount(pvm_int32 loopCount);
	virtual pvm_int32 GetLoopCount();
	virtual pvm_bool SetLoopInSamples(pvm_int64 /*loopFrom*/, pvm_int64 /*loopTo*/) { return false; }
	virtual pvm_bool GetLoopInSamples(pvm_int64& /*loopFrom*/, pvm_int64& /*loopTo*/) { return false; }
	virtual pvm_bool GetLoopInMS(pvm_int32& /*loopFrom*/, pvm_int32& /*loopTo*/) { return false; }

	virtual pvm_bool SetPositionMS(pvm_int32 position);
	virtual pvm_int32 GetPositionMS();

	virtual pvm_bool GetOption(const pvm_char* optionName, void* optionVal, pvm_uint32* optionSize);
	virtual pvm_bool SetOption(const pvm_char* optionName, void* optionVal, pvm_uint32 optionSize);


	static PVMVoiceMOD* Create(PVMVoiceSourceMOD* dataSource, pvm_int samplesPerSecond, pvm_int bitsPerSample, pvm_int chanelsNum);

	enum {EPVM_MOD_MAXCHANNEL=32};

	enum {EPVM_MOD_MAXSAMPLE=32};

	static pvm_uint32 TranslatePTSign(pvm_int8 *str);
protected:
	void Init(PVMVoiceSourceMOD* mod, pvm_int samplesPerSecond, pvm_int bitsPerSample, pvm_int chanelsNum);
	void stop();
	pvm_bool IsLoop();
	void NextLoop();
	void initTables(pvm_uint32 freq);
	pvm_uint32 findBestNoteIndex(pvm_uint32 note);

	static pvm_uint32 GetNumPattern(ModHeader *mh);
	static pvm_uint32 btol32(pvm_uint32 big);
	static pvm_uint16 btol16(pvm_uint16 big);
	static pvm_int8 getDigit(pvm_int8 a);
	static pvm_int8 getUpAlpha(pvm_int8 a);
	void pan(pvm_uint32 p);
protected:
	PVMVoiceSourceMOD*	source;

	const pvm_uint16* amiganote;
	const pvm_uint8*  sine;
	const pvm_uint32* gerdata;

	pvm_bool paused;
	pvm_int32 loopCount;

	pvm_int64 loopStart;
	pvm_int64 loopEnd;

	pvm_uint32 m_freqmix;
    pvm_uint32 m_virtfreq;
	pvm_uint32 m_freq;
	pvm_uint32 m_speed;
	pvm_bool m_changefreq;
	pvm_bool m_stereo;
	pvm_bool m_16bit;

    ModHeader *m_modheader;
    ModPattern *m_modpattern;
    pvm_uint32 m_numchl;
    pvm_uint32 m_pattern, m_note, m_seq, m_restart;
    pvm_uint32 m_bytextick, m_bytecnt;
    pvm_uint32 m_tickxdivision, m_tickcnt;
    pvm_uint32 m_finenoteidx[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_notefreq[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_sample[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_freqfactor[EPVM_MOD_MAXCHANNEL];
    pvm_int32 m_clcvol[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_glbvol[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_command[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_opx[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_opy[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_opxy[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_position[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_cpan[EPVM_MOD_MAXCHANNEL];

    pvm_uint32 m_slength[EPVM_MOD_MAXSAMPLE];
    pvm_uint32 m_sloopstart[EPVM_MOD_MAXSAMPLE];
    pvm_uint32 m_slooplength[EPVM_MOD_MAXSAMPLE];
    pvm_uint32 m_svol[EPVM_MOD_MAXSAMPLE];
    pvm_uint32 m_sfinetune[EPVM_MOD_MAXSAMPLE];
    pvm_uint32 m_sdata[EPVM_MOD_MAXSAMPLE];

    pvm_int32 m_voldelta[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_slideupdown[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_slidetonote[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_slidetonotedelta[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_arpeggioidx[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_arpeggiofq[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_arpeggiofqx[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_arpeggiofqy[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_vibratoidx[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_vibratospeed[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_vibratodepth[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_delaynote[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_delaynotefreq[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_tickcutsample[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_jumpseq;
    pvm_uint32 m_jumpnote;
    pvm_uint32 m_delaypattern;
    pvm_uint8 m_looppattern[EPVM_MOD_MAXCHANNEL];
    pvm_uint8 m_looppatternrow[EPVM_MOD_MAXCHANNEL];
    pvm_uint32 m_offset[EPVM_MOD_MAXCHANNEL];

	pvm_uint32 m_samplefreq[1713];
	pvm_uint16 m_noteidx[1713];

    pvm_uint32 m_bpm;

	pvm_bool bInterpolate;
};

#endif
